#include "mybisesocket.h"
#include "Interfaces/protocol.h"
#include "flowcontroler.h"
#include "Interfaces/frameprocess.h"

#include <QDataStream>
#include <QImage>
#include <QThread>

QStringList  MyBiseSocket::m_users;
MyBiseSocket::MyBiseSocket()
{
    connect(this, SIGNAL(readyRead()), this, SLOT(recvMsg()));
    connect(this, &MyBiseSocket::disconnected, this, [ = ]()
    {
        if(!m_user.isEmpty() && m_users.contains(m_user))
        {
            m_users.removeOne(m_user);
        }
    });
}

void MyBiseSocket::recvMsg()
{
    // 从套接字中读取所有数据
    QByteArray data = readAll();

    if (data.isEmpty())
    {
        qCritical() << "No data received from socket!";
        return;
    }

    QList<QByteArray> datas = FrameProcess::getDatas(data);


    for(auto &p : datas)
    {
        // 使用 QDataStream 解析数据
        QDataStream stream(p);
        stream.setByteOrder(QDataStream::BigEndian); // 假设使用大端序

        // 计算 PBS 数据大小
        uint PBSLen = 0;
        stream.readRawData((char*)&PBSLen, sizeof (uint));

        if(PBSLen != 0)
        {
            // 分配内存并读取 PBS 数据
            PBS* pbs = (PBS*)malloc(PBSLen);

            if (!pbs)
            {
                qCritical() << "Memory allocation failed for PBS!";
                return;
            }

            memset(pbs, 0, PBSLen); // 初始化 PBS 内存
            pbs->PBSLen = PBSLen;
            stream.readRawData((char*)(pbs ) + sizeof (uint), PBSLen - sizeof (uint));

            handlePBS(pbs);
        }
    }


}

void MyBiseSocket::sendDataToClien(PBS *pbs)
{

    if (!pbs)
    {
        qCritical() << "PBS is null, cannot send!";
        return;
    }
    // 计算 PBS 的总大小
    int totalSize = pbs->PBSLen;

    // 将帧头和长度添加到数据流中
    QByteArray byteArray;
    QDataStream stream(&byteArray, QIODevice::WriteOnly);
    stream.setByteOrder(QDataStream::BigEndian); // 设置字节序（可选，使用大端序）


    // 写入 PBS 数据
    stream.writeRawData(reinterpret_cast<char*>(pbs), totalSize);

    // 加帧头帧尾
    QByteArray data = FrameProcess::addFrame(byteArray);

    // 发送数据
    qint64 bytesSent = write(data);
    if (bytesSent == -1)
    {
        qCritical() << "Failed to send PBS data!";
    }
    else
    {
        qDebug() << "Sent" << bytesSent << "bytes of PBS data";
    }

    // 确保数据已经发送
    flush();
    waitForBytesWritten();
}

void MyBiseSocket::handlePBS(PBS *pbs)
{
    switch (pbs->MsgType)
    {
        case REGIST_REQUEST:
            {
                Core::User newUser = deserializePBSToUser(pbs);
                FlowControler::Interface->registerUser(newUser);
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = mkPBS(0);
                respbs->MsgType = REGIST_RESPOND;
                respbs->Code = code;
                //qDebug() << respbs->MsgType;
//        if(ret){
//            strncpy(respbs->caData,REGIST_OK,32);
//        }else{
//            strncpy(respbs->caData,REGIST_FAILED,32);
//        }
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;
                break;
            }
        case LOGIN_REQUEST:
            {
                Core::User user = deserializePBSToUser(pbs);
                PBS *respbs = nullptr;
                if(m_users.contains(user.name))
                {
                    respbs = mkPBS(0);
                    respbs->MsgType = LOGIN_RESPOND;
                    respbs->Code = UserLogined;
                    sendDataToClien(respbs);
                    free(respbs);
                    respbs = NULL;

                    break;
                }
                else
                {
                    FlowControler::Interface->login(user);
                    int code = FlowControler::Interface->getLastError();

                    if(code == NoError)
                    {
                        Core::User curUser = *FlowControler::Interface->getCurrentUser();
                        respbs = serializeUserToPBS(curUser);
                        m_user = user.name;
                        m_users.append(user.name);

                    }
                    else
                    {
                        respbs = mkPBS(0);
                    }
                    respbs->MsgType = LOGIN_RESPOND;
                    respbs->Code = code;
                    sendDataToClien(respbs);
                    free(respbs);
                    respbs = NULL;

                    break;
                }
            }
        case LOGOUT_REQUEST:
            {
                Core::User user = deserializePBSToUser(pbs);
                if(m_users.contains(m_user))
                {
                    m_users.removeOne(m_user);
                }
                PBS *respbs = mkPBS(0);
                respbs->MsgType = LOGOUT_RESPOND;
                respbs->Code = NoError;
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;

                break;
            }
        case UPDATE_USER_REQUEST:
            {
                Core::User newUser = deserializePBSToUser(pbs);
                FlowControler::Interface->updateUser(newUser);
                int code = FlowControler::Interface->getLastError();
                PBS *respbs = nullptr;
                if(code == NoError)
                {
                    Core::User curUser = *FlowControler::Interface->getCurrentUser();
                    respbs = serializeUserToPBS(curUser);

                }
                else
                {
                    respbs = mkPBS(0);
                }
                respbs->MsgType = UPDATE_USER_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;
                break;
            }
        case ADD_ANIME_REQUEST:
            {
                Core::Anime anime = deserializePBSToAnime(pbs);
                FlowControler::Interface->addAnime(anime);
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = mkPBS(0);
                respbs->MsgType = ADD_ANIME_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;
                break;
            }
        case DELETE_ANIME_REQUEST:
            {
                Core::Anime anime = deserializePBSToAnime(pbs);
                FlowControler::Interface->deleteAnime(anime);
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = mkPBS(0);
                respbs->MsgType = DELETE_ANIME_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;
                break;
            }
        case UPDATE_ANIME_REQUEST:
            {
                Core::Anime anime = deserializePBSToAnime(pbs);
                FlowControler::Interface->updateAnime(anime);
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = mkPBS(0);
                respbs->MsgType = UPDATE_ANIME_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;

                break;
            }
        case GET_ALL_ANIMES_REQUEST:
            {
                QList<Core::Anime> animes = FlowControler::Interface->getAllAnimes();

                // 组装anime发送至客户端
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = serializeAnimesToPBS(animes);
                respbs->MsgType = GET_ALL_ANIMES_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;
                break;
            }
        case BROWSE_BY_CATEGORY_REQUEST:
            {
                PBS *respbs = mkPBS(0);
                respbs->MsgType = BROWSE_BY_CATEGORY_RESPOND;
                respbs->Code = NoError;
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;
                break;
            }
        case BROWSE_BY_TAG_REQUEST:
            {
                Core::Filter filter = deserializePBSToFilter(pbs);
                QList<Core::Anime> animes = FlowControler::Interface->browseByTag(filter);
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = serializeAnimesToPBS(animes);
                respbs->MsgType = BROWSE_BY_TAG_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;
                break;
            }
        case COMMENT_ANIME_REQUEST:
            {
                Core::Comment comment = deserializePBSToComment(pbs);
                FlowControler::Interface->commentAnime(comment);
                int code = FlowControler::Interface->getLastError();


                PBS *respbs = mkPBS(0);
                respbs->MsgType = COMMENT_ANIME_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;
                break;
            }
        case ACCEPT_COMMENT_ANIME_REQUEST:
            {
                Core::Comment comment = deserializePBSToComment(pbs);
                FlowControler::Interface->acceptComment(comment);
                int code = FlowControler::Interface->getLastError();


                PBS *respbs = mkPBS(0);
                respbs->MsgType = ACCEPT_COMMENT_ANIME_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = NULL;
                break;
            }
        case REJECT_COMMENT_ANIME_REQUEST:
            {
                Core::Comment comment = deserializePBSToComment(pbs);
                FlowControler::Interface->rejectComment(comment);
                int code = FlowControler::Interface->getLastError();


                PBS *respbs = mkPBS(0);
                respbs->MsgType = REJECT_COMMENT_ANIME_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = nullptr;
                break;
            }
        case GET_ALL_PENDING_COMMENTS_REQUEST:
            {
                QList<Core::Comment> comments = FlowControler::Interface->getPendingComment();
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = serializePostCommentsToPBS(comments);
                respbs->MsgType = GET_ALL_PENDING_COMMENTS_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = nullptr;
                break;
            }
        case POST_REQUEST:
            {
                Core::Post post = deserializePBSToPost(pbs);
                FlowControler::Interface->post(post);
                int code = FlowControler::Interface->getLastError();

                qDebug() << "图片大小：" << post.pixSize;

                PBS *respbs =  post.pixSize > 0 ? serializeQStringToPBS(QString::number(post.id)) : mkPBS(0);
                respbs->MsgType = post.pixSize > 0 ? GET_POST_ID  : POST_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = nullptr;
                break;
            }
        case GET_POSTS_REQUEST:
            {
                FlowControler::Interface->m_havePixmapPost.clear();
                QList<Core::Post> posts = FlowControler::Interface->getPosts(10);
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = serializePostsToPBS(posts);
                respbs->MsgType = GET_POSTS_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = nullptr;

                if(FlowControler::Interface->m_havePixmapPost.size() > 0)
                {
                    sendPixToClient();
                }
                break;
            }
        case ACCEPT_POST_REQUEST:
            {
                Core::Post post = deserializePBSToPost(pbs);
                FlowControler::Interface->acceptpost(post);
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = mkPBS(0);
                respbs->MsgType = ACCEPT_POST_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = nullptr;
                break;
            }
        case REJECT_POST_REQUEST:
            {
                Core::Post post = deserializePBSToPost(pbs);
                FlowControler::Interface->rejectpost(post);
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = mkPBS(0);
                respbs->MsgType = REJECT_POST_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = nullptr;
                break;
            }
        case GET_ALL_PENDING_POSTS_REQUEST:
            {
                QList<Core::Post> posts = FlowControler::Interface->getPendingPost();
                int code = FlowControler::Interface->getLastError();


                PBS *respbs = serializePostsToPBS(posts);
                respbs->MsgType = GET_ALL_PENDING_POSTS_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = nullptr;
                break;
            }
        case POST_COMMENT_REQUEST:
            {
                Core::PostComment comment = deserializePBSToPostComment(pbs);
                FlowControler::Interface->postComment(comment);
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = mkPBS(0);
                respbs->MsgType = POST_COMMENT_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = nullptr;
                break;
            }
        case LIKE_POST_REQUEST:
            {
                Core::LikePost like = deserializePBSToLikePost(pbs);
                FlowControler::Interface->likePost(like);
                int code = FlowControler::Interface->getLastError();

                PBS *respbs = mkPBS(0);
                respbs->MsgType = LIKE_POST_RESPOND;
                respbs->Code = code;
                sendDataToClien(respbs);
                free(respbs);
                respbs = nullptr;
                break;
            }
        case PIX_FROM_POST_SEND:
            {
                Core::PixFromPost info = deserializePBSToPixFromPost(pbs);
                m_pix_buf.append(info.pix_buf);
                qDebug() << "【Server:】 帖子ID:" << info.postId << "当前接收图片字节：" << info.pix_buf.size() << "图片已收到累积字节：" << m_pix_buf.size();
                if(info.pix_buf.size() < 1024)
                {
                    info.pix_buf = m_pix_buf;
                    m_pix_buf.clear();
                    FlowControler::Interface->savePixToDB(info);
                    PBS *respbs = mkPBS(0);
                    respbs->MsgType = PIX_FROM_POST_RESPOND;
                    respbs->Code = FlowControler::Interface->getLastError();
                    sendDataToClien(respbs);
                    free(respbs);
                    respbs = nullptr;
                    break;
                }
                break;
            }
        default:
            break;
    }

    free(pbs);
    pbs = nullptr;

}

void MyBiseSocket::sendPixToClient()
{
    auto list = FlowControler::Interface->m_havePixmapPost;
    for (int i = 0; i < list.size(); ++i)
    {
        auto info = list.at(i);
        qint64 pixSize = info.pix_buf.size();
        if(pixSize > 0)
        {
            qDebug() << pixSize << "Org Pix Size;";
            qint64 bytesToSend = pixSize;
            const int chunkSize = 1024;
            int bytesSent = 0;
            int cnt = 0;
            while (bytesToSend > 0)
            {
                qint64 diffSize = qAbs(pixSize - bytesSent);
                bool isEnd = qAbs(pixSize - bytesSent) < chunkSize;
                QByteArray chunk = info.pix_buf.mid(bytesSent, isEnd ? int(diffSize) : chunkSize);

                Core::PixFromPost t_info;
                t_info.postId = info.postId;
                t_info.pix_buf = chunk;

                qDebug() << "cnt" << ++cnt << "buf size " << chunk.size();
                PBS *pbs = serializePixFromPostToPBS(t_info);
                pbs->Code = NoError;
                sendDataToClien(pbs);

                bytesToSend -= chunk.size();
                bytesSent += chunk.size();

                QThread::msleep(2);
            }
        }
        QThread::msleep(10);
    }
}
